﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Timers;
using System.Xml.Linq;
using Common;

namespace AnesAutoUpdate
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        Timer timer = new Timer();
        AutoUpdateConfigModel updateXML = new AutoUpdateConfigModel();
        LocalXMLModel localXML = new LocalXMLModel();
        bool tipIsShow = false;

        public MainWindow()
        {
            InitializeComponent();
            try
            {

                timer.Interval = ClientAndServerHelper.Instance.UpdateXMLContent.UpdateTimer;
                RunTask();
                this.Loaded += MainWindow_Loaded;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void Check()
        {
            localXML = GetLocalInfoContent();
            if (localXML == null)
            {
                TipMessageAndCloseWin("丢失配置文件，请联系工程师！");
            }
            if (!PingServer())
            {
                TipMessageAndCloseWin("连接服务器失败，请检查网络连接；/n您还可以联系管理员或者稍后再试！");
            }
        }

        private LocalXMLModel GetLocalInfoContent()
        {
            try
            {
                return (new ClientAndServerHelper()).GetLocalXmlContent();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void TipMessageAndCloseWin(string msg)
        {
            MessageBox.Show(msg, "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
            CloseSys();
        }
        private bool PingServer()
        {
            return IPHelper.PingIP(localXML.SerIp);
        }

        private void UpdateRunExe()
        {
            try
            {
                ClientAndServerHelper.Instance.DownloadFiles(true, false);
            }
            catch (Exception ex)
            {
                KillAllProcesses();
                LogHelper.Error(this.GetType(), ex);
            }
        }

        private void RunTask()
        {
            Task.Factory.StartNew((Action)delegate
            {
                try
                {
                    LogHelper.Fatal(this.GetType(), "start Init");
                    Init();
                    LogHelper.Fatal(this.GetType(), "end Init");
                    LogHelper.Fatal(this.GetType(), "start UpdateSys");
                    UpdateSys();
                    LogHelper.Fatal(this.GetType(), "end UpdateSys");
                    LogHelper.Fatal(this.GetType(), "start FinallyOperate");
                    FinallyOperate();
                    LogHelper.Fatal(this.GetType(), "end FinallyOperate");
                    LogHelper.Fatal(this.GetType(), "start Dispatcher.Invoke((Action)delegate");
                    Dispatcher.Invoke((Action)delegate
                    {
                        this.Visibility = Visibility.Collapsed;
                        LogHelper.Fatal(this.GetType(), "Close");
                        timer.Start();
                    });
                    LogHelper.Fatal(this.GetType(), "end +Dispatcher.Invoke((Action)delegate");
                }
                catch (Exception ex)
                {
                    LogHelper.Error(this.GetType(), ex);
                    MessageBox.Show(ex.Message);
                    Dispatcher.Invoke((Action)delegate
                    {
                        this.Close();
                    });
                }
            });
        }

        private void UpdateSys()
        {
            try
            {
                LogHelper.Fatal(this.GetType(), "CheckVersion");
                int res = CheckVersion();
                LogHelper.Fatal(this.GetType(), string.Format("local:{0};server{1}", localXML.LocalVersion, updateXML.ServerVersion));
                LogHelper.Fatal(this.GetType(), "end CheckVersion");
                LogHelper.Fatal(this.GetType(), "KillAllProcesses");
                KillAllProcesses();
                LogHelper.Fatal(this.GetType(), "end KillAllProcesses");
                LogHelper.Fatal(this.GetType(), "UpdateRunExe");
                //UpdateRunExe();
                LogHelper.Fatal(this.GetType(), "end UpdateRunExe");
                if (res == 1)
                {
                    Dispatcher.Invoke((Action)delegate
                    {
                        this.lblMessage.Content = "系统更新中...";
                    });
                    Task task = Task.Factory.StartNew(() =>
                    {
                        LogHelper.Fatal(this.GetType(), "UpdateSystem");
                        UpdateSystem();
                    });
                    task.Wait();
                    Dispatcher.Invoke((Action)delegate
                    {
                        LogHelper.Fatal(this.GetType(), "end UpdateSystem");
                        LogHelper.Fatal(this.GetType(), "start 弹框提示更新信息");
                        MessageWin win = new MessageWin();
                        win.btnYes.Content = "确定";
                        win.btnNo.Visibility = Visibility.Collapsed;
                        tipIsShow = true;
                        win.Message = updateXML.UpdateDetial;
                        win.ShowDialog();
                        LogHelper.Fatal(this.GetType(), "end 弹框提示更新信息");
                        tipIsShow = false;
                        this.lblMessage.Content = "系统更新完毕";
                    });
                }
                else
                {
                    LogHelper.Fatal(this.GetType(), "StartRestartExe");
                    StartRestartExe();
                    LogHelper.Fatal(this.GetType(), "StartRestartExe");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void FinallyOperate()
        {
            try
            {
                ProcessStartExe();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void UpdateSystem()
        {
            try
            {
                LogHelper.Fatal(this.GetType(), "DownloadUpdateFiles");
                DownloadUpdateFiles();
                LogHelper.Fatal(this.GetType(), "end DownloadUpdateFiles");
                LogHelper.Fatal(this.GetType(), "StartRestartExe");
                StartRestartExe();
                LogHelper.Fatal(this.GetType(), "end StartRestartExe");
                LogHelper.Fatal(this.GetType(), "WriteVersionToLocal");
                WriteVersionToLocal();
                LogHelper.Fatal(this.GetType(), "end WriteVersionToLocal");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void StartRestartExe()
        {
            try
            {
                foreach (string str in updateXML.StartProcess)
                {
                    if (File.Exists(str))
                    {
                        Process.Start(str);
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(this.GetType(), ex);
                throw new StartProcessFailedException();
            }
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            timer.Elapsed += Timer_Elapsed;
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            try
            {
                timer.Stop();
                if (!tipIsShow)
                {
                    int res = CheckVersion();
                    if (res == 1)
                    {
                        FileInfo file = new FileInfo(updateXML.RealStartExePath);
                        string name = file.Name.Replace(".exe", "");
                        if (Process.GetProcessesByName(name).Length == 0)
                        {
                            //UpdateSystem();
                        }
                        else
                        {
                            Dispatcher.Invoke((Action)delegate
                            {
                                MessageWin win = new MessageWin();
                                tipIsShow = true;
                                win.btnYes.Content = "急速升级";
                                win.btnNo.Visibility = Visibility.Visible;
                                win.Message = updateXML.UpdateDetial;
                                win.ShowDialog();
                                if (win.Result)
                                {
                                    tipIsShow = false;
                                    Process.Start("Run.exe");
                                    CloseSys();
                                }
                                else
                                {
                                    tipIsShow = false;
                                    timer.Interval = updateXML.UpdateTimer;
                                }
                            });
                        }
                    }
                    else if (res == 4)
                    {
                        //UpdateShouMaSys();
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(this.GetType(), ex);
            }
            finally
            {
                timer.Start();
            }
        }

        private void Init()
        {
            try
            {
                LogHelper.Fatal(this.GetType(), "GetAutoupateContent");
                GetAutoupateContent();
                LogHelper.Fatal(this.GetType(), "end GetAutoupateContent");
                LogHelper.Fatal(this.GetType(), "GetUpdateXMLContent");
                GetUpdateXMLContent();
                LogHelper.Fatal(this.GetType(), "end GetUpdateXMLContent");
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        private void CloseSys()
        {
            this.Close();
            return;
        }

        /// <summary>
        /// 1:update 2:delete 3:noUpdate 4:强制更新
        /// </summary>
        /// <returns></returns>
        private int CheckVersion()
        {
            try
            {
                ClientAndServerHelper.Instance.LoadXML();
                localXML = ClientAndServerHelper.Instance.GetLocalXmlContent();
                updateXML = ClientAndServerHelper.Instance.GetUpdateContent();

                if (localXML.LocalVersion < updateXML.ServerVersion)
                {
                    if (bool.Parse(updateXML.Qzgx))
                    {
                        return 4;
                    }
                    return 1;
                }
                else
                    return 3;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void KillAllProcesses()
        {
            try
            {
                Process currentPro = Process.GetCurrentProcess();
                foreach (string proName in updateXML.KillProcess)
                {
                    ProcessHelper.KillProcessByName(proName, currentPro);
                    LogHelper.Fatal(this.GetType(), "KillProcessByName" + proName);
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(this.GetType(), ex);
            }
        }

        private void DownloadUpdateFiles()
        {
            try
            {
                ClientAndServerHelper.Instance.DownloadFiles(false, false, updateXML);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void GetUpdateXMLContent()
        {
            try
            {
                updateXML = ClientAndServerHelper.Instance.UpdateXMLContent;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void GetAutoupateContent()
        {
            try
            {
                localXML = ClientAndServerHelper.Instance.LocalXMLContent;
            }
            catch (Exception ex)
            {
                LogHelper.Error(this.GetType(), ex);
                throw new XMLParsingFailedException();
            }
        }

        private void ProcessStartExe()
        {
            try
            {
                Process.Start(updateXML.RealStartExePath);
            }
            catch (Exception ex)
            {
                LogHelper.Error(this.GetType(), ex);
                throw new StartProcessFailedException();
            }
        }

        private void WriteVersionToLocal()
        {
            try
            {
                ClientAndServerHelper.Instance.WriteVersionToLocal();
            }
            catch (Exception ex)
            {
                LogHelper.Error(this.GetType(), ex);
                throw ex;
            }
        }
    }
}
